package com.vinny.springbootflowable.controller;

import com.vinny.springbootflowable.common.ApiResponse;
import com.vinny.springbootflowable.common.HttpStatus;
import com.vinny.springbootflowable.util.BusinessKeyGenerator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.SequenceFlow;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 报销流程控制器
 * 同时支持页面渲染和RESTful API
 */
@Tag(name = "报销流程", description = "报销流程相关接口")
@Controller
@RequestMapping("/expense")
public class ExpenseController {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private BusinessKeyGenerator businessKeyGenerator;

    // ================ 视图相关接口 ================

    /**
     * 跳转到报销申请页面
     */
    @GetMapping("/apply")
    public String applyForm() {
        return "expense/apply";
    }

    /**
     * 跳转到任务列表页面
     */
    @GetMapping("/tasks")
    public String tasksPage(Authentication authentication, Model model) {
        // 获取任务列表
        List<Task> tasks = taskService.createTaskQuery()
                .taskCandidateOrAssigned(authentication.getName())
                .orderByTaskCreateTime()
                .desc()
                .list();

        // 获取每个任务的历史评论
        Map<String, List<String>> taskComments = new HashMap<>();
        for (Task task : tasks) {
            List<String> comments = taskService.getTaskComments(task.getId()).stream()
                    .map(comment -> comment.getFullMessage())
                    .toList();
            taskComments.put(task.getId(), comments);
        }

        model.addAttribute("tasks", tasks);
        model.addAttribute("taskComments", taskComments);
        return "expense/tasks";
    }

    /**
     * 获取流程图
     */
    @GetMapping("/processDiagram")
    public void generateProcessDiagram(HttpServletResponse response,
            @RequestParam String processInstanceId) throws Exception {
        
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();

        if (processInstance == null) {
            return;
        }

        // 获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        ProcessEngineConfiguration engineConfig = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engineConfig.getProcessDiagramGenerator();

        // 获取当前活动的节点
        List<String> activeActivityIds = runtimeService.getActiveActivityIds(processInstanceId);
        
        // 获取已完成的活动节点
        List<String> highLightedFlows = new ArrayList<>();
        // 如果流程还在运行，获取流程线
        if (processInstance != null) {
            // 获取流程历史中已完成的节点
            List<HistoricActivityInstance> historicActivityInstances = historyService
                    .createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .finished()
                    .orderByHistoricActivityInstanceStartTime()
                    .asc()
                    .list();

            // 从已完成的节点中获取流程线
            List<String> historicActivityIds = historicActivityInstances.stream()
                    .map(HistoricActivityInstance::getActivityId)
                    .collect(Collectors.toList());

            // 获取当前活动的流程线
            for (int i = 0; i < historicActivityIds.size() - 1; i++) {
                String sourceActivityId = historicActivityIds.get(i);
                String targetActivityId = historicActivityIds.get(i + 1);
                List<SequenceFlow> sequenceFlows = bpmnModel.getMainProcess().findFlowElementsOfType(SequenceFlow.class);
                for (SequenceFlow flow : sequenceFlows) {
                    if (flow.getSourceRef().equals(sourceActivityId) && flow.getTargetRef().equals(targetActivityId)) {
                        highLightedFlows.add(flow.getId());
                    }
                }
            }
        }

        response.setContentType("image/png");
        try (InputStream in = diagramGenerator.generateDiagram(
                bpmnModel,
                "png",
                activeActivityIds,
                highLightedFlows,
                engineConfig.getActivityFontName(),
                engineConfig.getLabelFontName(),
                engineConfig.getAnnotationFontName(),
                engineConfig.getClassLoader(),
                1.0,
                true);  // 开启颜色
             OutputStream out = response.getOutputStream()) {
            
            byte[] buf = new byte[1024];
            int length;
            while ((length = in.read(buf)) != -1) {
                out.write(buf, 0, length);
            }
        }
    }

    /**
     * 获取流程图
     */
    @Operation(summary = "获取流程图")
    @GetMapping("/api/diagram/{processInstanceId}")
    public void getProcessDiagram(HttpServletResponse response,
            @Parameter(description = "流程实例ID") @PathVariable String processInstanceId) throws Exception {
        generateProcessDiagram(response, processInstanceId);
    }

    // ================ RESTful API 接口 ================

    /**
     * 提交报销申请
     */
    @Operation(summary = "提交报销申请")
    @ApiResponses(value = {
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "提交成功"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "请求参数错误")
    })
    @PostMapping("/api/submit")
    @ResponseBody
    public ApiResponse<String> submitExpense(
            @Parameter(description = "报销申请信息") @RequestBody Map<String, Object> request,
            Authentication authentication) {
        
        Double amount = ((Number) request.get("amount")).doubleValue();
        String description = (String) request.get("description");
        
        // 创建流程变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("amount", amount);
        variables.put("description", description);
        
        // 生成业务键
        String businessKey = businessKeyGenerator.generateBusinessKey();
        
        // 启动流程实例
        String processInstanceId = runtimeService.startProcessInstanceByKey(
            "Expense",
            businessKey,
            variables
        ).getId();

        // 获取并完成员工任务
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)
                .taskAssignee(authentication.getName())
                .singleResult();
        
        if (task != null) {
            // 添加提交说明
            taskService.addComment(
                task.getId(),
                processInstanceId,
                String.format("提交报销申请：金额 %.2f元，说明：%s", amount, description)
            );
            taskService.complete(task.getId(), variables);
        }

        return ApiResponse.success("提交成功", processInstanceId);
    }

    /**
     * 获取任务列表
     */
    @Operation(summary = "获取待办任务列表")
    @GetMapping("/api/tasks")
    @ResponseBody
    public ApiResponse<List<Map<String, Object>>> getTasks(Authentication authentication) {
        List<Task> tasks = taskService.createTaskQuery()
                .taskCandidateOrAssigned(authentication.getName())
                .orderByTaskCreateTime()
                .desc()
                .list();

        List<Map<String, Object>> taskList = tasks.stream()
                .map(task -> {
                    Map<String, Object> taskMap = new HashMap<>();
                    taskMap.put("id", task.getId());
                    taskMap.put("name", task.getName());
                    taskMap.put("createTime", task.getCreateTime());
                    taskMap.put("assignee", task.getAssignee());
                    taskMap.put("processInstanceId", task.getProcessInstanceId());
                    return taskMap;
                })
                .toList();

        return ApiResponse.success(taskList);
    }

    /**
     * 完成任务
     */
    @Operation(summary = "完成任务")
    @ApiResponses(value = {
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "审批完成"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "任务不存在或无权处理")
    })
    @PostMapping("/api/complete/{taskId}")
    @ResponseBody
    public ApiResponse<Void> completeTask(
            @Parameter(description = "任务ID") @PathVariable String taskId,
            @Parameter(description = "审批信息") @RequestBody Map<String, Object> request,
            Authentication authentication) {
        
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskCandidateOrAssigned(authentication.getName())
                .singleResult();

        if (task == null) {
            return ApiResponse.error(HttpStatus.NOT_FOUND, "任务不存在或无权处理");
        }

        String outcome = (String) request.get("outcome");
        String comment = (String) request.get("comment");

        // 添加审批意见
        taskService.addComment(taskId, task.getProcessInstanceId(), 
            outcome + "：" + comment);

        // 完成任务，只传递outcome变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("outcome", outcome);
        taskService.complete(taskId, variables);

        return ApiResponse.success("审批完成", null);
    }

    /**
     * 重新提交任务
     */
    @Operation(summary = "重新提交任务")
    @ApiResponses(value = {
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "重新提交成功"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "任务不存在或无权处理")
    })
    @PostMapping("/api/resubmit/{taskId}")
    @ResponseBody
    public ApiResponse<Void> resubmitTask(
            @Parameter(description = "任务ID") @PathVariable String taskId,
            @Parameter(description = "重新提交信息") @RequestBody Map<String, Object> request,
            Authentication authentication) {
        
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskAssignee(authentication.getName())
                .singleResult();

        if (task == null) {
            return ApiResponse.error(HttpStatus.NOT_FOUND, "任务不存在或无权处理");
        }

        Double amount = ((Number) request.get("amount")).doubleValue();
        String description = (String) request.get("description");

        // 添加重新提交说明
        taskService.addComment(taskId, task.getProcessInstanceId(),
            String.format("重新提交：金额 %.2f元，说明：%s", amount, description));

        // 完成任务
        Map<String, Object> variables = new HashMap<>();
        variables.put("amount", amount);
        variables.put("description", description);
        taskService.complete(taskId, variables);

        return ApiResponse.success("重新提交成功", null);
    }

    /**
     * 获取流程状态
     */
    @Operation(summary = "获取流程状态")
    @GetMapping("/api/process/{processInstanceId}")
    @ResponseBody
    public ApiResponse<Map<String, Object>> getProcessStatus(
            @Parameter(description = "流程实例ID") @PathVariable String processInstanceId) {
        
        Map<String, Object> status = new HashMap<>();
        boolean isActive = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult() != null;

        status.put("status", isActive ? "进行中" : "已完成");
        return ApiResponse.success(status);
    }

    /**
     * 获取流程评论
     */
    @GetMapping("/api/comments/{processInstanceId}")
    @ResponseBody
    public ApiResponse<List<String>> getProcessComments(
            @PathVariable String processInstanceId) {
        
        List<String> comments = taskService.getProcessInstanceComments(processInstanceId)
                .stream()
                .map(comment -> comment.getFullMessage())
                .toList();

        return ApiResponse.success(comments);
    }

    // ================ 表单提交处理 ================

    /**
     * 处理表单提交的报销申请
     */
    @PostMapping("/submit")
    public String handleFormSubmit(
            @RequestParam("amount") Double amount,
            @RequestParam(value = "description", required = false) String description,
            Authentication authentication) {
        
        // 创建流程变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("amount", amount);
        if (description != null && !description.trim().isEmpty()) {
            variables.put("description", description);
        }
        
        // 生成业务键
        String businessKey = businessKeyGenerator.generateBusinessKey();
        
        // 启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
            "Expense",
            businessKey,
            variables
        );

        // 获取并完成员工任务
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstance.getId())
                .taskAssignee(authentication.getName())
                .singleResult();
        
        if (task != null) {
            // 添加提交说明
            taskService.addComment(
                task.getId(),
                processInstance.getId(),
                String.format("提交报销申请：金额 %.2f元%s",
                    amount,
                    description != null ? "，说明：" + description : "")
            );
            taskService.complete(task.getId(), variables);
        }

        return "redirect:/expense/tasks";
    }

    /**
     * 处理表单提交的任务完成
     */
    @PostMapping("/complete/{taskId}")
    public String handleFormComplete(
            @PathVariable String taskId,
            @RequestParam("outcome") String outcome,
            @RequestParam(value = "comment", required = false) String comment) {
        
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .singleResult();
        
        if (task != null) {
            // 添加审批意见
            taskService.addComment(taskId, task.getProcessInstanceId(),
                outcome + (comment != null ? "：" + comment : ""));

            // 完成任务
            Map<String, Object> variables = new HashMap<>();
            variables.put("outcome", outcome);
            taskService.complete(taskId, variables);
        }

        return "redirect:/expense/tasks";
    }
} 